package com.gzhryc.shared_device.iot.core.hryc;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.event.TriggerService;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.shared_device.iot.core.*;
import com.gzhryc.shared_device.iot.core.enums.EIOTDeviceState;
import com.gzhryc.shared_device.iot.core.enums.EIOTType;
import com.gzhryc.shared_device.iot.core.hryc.models.HRYCIOTConfig;
import com.gzhryc.shared_device.iot.core.hryc.models.HRYCIOTSynResponse;
import com.gzhryc.socket.SocketCallback;
import com.gzhryc.socket.SocketConfig;
import com.gzhryc.socket.SocketEvent;
import com.gzhryc.socket.message.MqttSocketMessage;
import com.gzhryc.socket.mosquitto.MosquittoThreadPoolMqttClient;

import java.util.concurrent.TimeUnit;

public class HRYCSmartMqttIotClient implements IOTClient {

	final static Logger log = Logger.getLogger(HRYCSmartMqttIotClient.class);
	
	private static final String SYS_TOPIC_CONNECTED = "$SYS/brokers/+/clients/+/connected";
	private static final String SYS_TOPIC_DISCONNECTED = "$SYS/brokers/+/clients/+/disconnected";

	final MosquittoThreadPoolMqttClient mClient;
	final IOTNodeEntity mIOTNode;
	final HRYCIOTConfig mConfig;

	final IOTClientEventListener mListener;

	public HRYCSmartMqttIotClient(HRYCIOTConfig config, IOTNodeEntity iotNode,IOTClientEventListener listener) {
		this.mConfig = config;
		this.mListener = listener;
		this.mIOTNode = iotNode;
		SocketConfig socketConfig = ClassTools.copy(new SocketConfig(),config);
		this.mClient = new MosquittoThreadPoolMqttClient(socketConfig, new IOTMqttClientCallback(this, listener));
	}

	@Override
	public boolean send(IOTMessage msg) {
		try {
			String topic = "/" + mConfig.getProductKey() + msg.getTopic();
			int qos = 0;
			MqttSocketMessage mqttMsg = new MqttSocketMessage(topic, qos, msg.getBytes());
			if (mClient.writeAndFlush(mqttMsg)) {
				try {
					mListener.sendMessage(msg, mConfig.getIotId(), topic);
				} catch (Exception e) {
					log.error(e.getMessage(), e);
				}
				return true;
			}
		} catch (Exception e) {
			log.error("发送MQTT消息错误", e);
		}
		return false;
	}

	@Override
	public void run() {
		mClient.startService();
	}

	private class IOTMqttClientCallback implements SocketCallback {

		IOTClientEventListener listener;
		HRYCSmartMqttIotClient client;

		public IOTMqttClientCallback(HRYCSmartMqttIotClient client, IOTClientEventListener listener) {
			this.client = client;
			this.listener = listener;
		}

		@Override
		public void active(SocketEvent event) {
			listener.active(new HRYCSmartClientEvent(client, event));
			String topic = "/" + mConfig.getProductKey() + "/+/user/update";
			mClient.subscribe(topic, 0);
			log.info("MQTT客户端激活，订阅主题：" + topic);

			mClient.subscribe(SYS_TOPIC_CONNECTED, 0);
			log.info("MQTT客户端激活，订阅主题：" + SYS_TOPIC_CONNECTED);
			mClient.subscribe(SYS_TOPIC_DISCONNECTED, 0);
			log.info("MQTT客户端激活，订阅主题：" + SYS_TOPIC_DISCONNECTED);
		}

		@Override
		public void connected(SocketEvent event) {
		}

		@Override
		public void connectionLost(SocketEvent event) {
			log.error("MQTT客户端连接失败", event.getCause());
		}

		@Override
		public void messageArrived(SocketEvent event) {
			MqttSocketMessage mqttMsg = event.getMessage(MqttSocketMessage.class);
			if (mqttMsg.getTopic().startsWith("$SYS")) {
				if (mqttMsg.getTopic().endsWith("/connected")) {
					HRYCSmartDeviceStateEvent messageEvent = new HRYCSmartDeviceStateEvent(client, mqttMsg, EIOTDeviceState.Online);
					listener.stateChange(messageEvent);
				} else if (mqttMsg.getTopic().endsWith("/disconnected")) {
					HRYCSmartDeviceStateEvent messageEvent = new HRYCSmartDeviceStateEvent(client, mqttMsg, EIOTDeviceState.Offline);
					listener.stateChange(messageEvent);
				} else {
					log.error("骁匠物联，无法识别的主题：{{0}}", mqttMsg.getTopic());
				}
			}else {
				HRYCSmartClientEvent messageEvent = new HRYCSmartClientEvent(client, event);
				messageEvent.setMqttMsg((MqttSocketMessage) event.getMessage());
				listener.receiveMessage(messageEvent);
			}
		}

		@Override
		public void deliveryComplete(SocketEvent event) {
		}

		@Override
		public void close(SocketEvent event) {
			log.error("MQTT客户端连接关闭", event.getCause());
		}

	}

	@Override
	public IOTSynResponse synSend(IOTMessage msg, Long times, TimeUnit unit) {
		if (TriggerService.get().hasTriggerLock(msg.getMessageId())) {
			return null; // 等待上一个结束
		}
		TriggerService.get().setTriggerLock(msg.getMessageId(), times, unit);
		if (mClient.writeAndFlush(msg)) {
			Object obj = TriggerService.get().getData(msg.getMessageId(), times, unit);
			if (obj != null) {
				IOTSynResponse result = new HRYCIOTSynResponse(obj);
				return result;
			}
		}
		return null;
	}

	@Override
	public void close() {

	}

	@Override
	public EIOTType getIOTType() {
		return EIOTType.HRYC_SMART;
	}

	@Override
	public IOTNodeEntity getIOTNote() {
		return this.mIOTNode;
	}


}
